package com.ruoyi.grpc;


import com.google.protobuf.ByteString;
import com.ruoyi.grpc.generate.AsrServiceGrpc;
import com.ruoyi.grpc.generate.AudioStreaming;
import io.grpc.Channel;
import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class AsrClient {

    private static final Logger log = LoggerFactory.getLogger(AsrClient.class);

    private ManagedChannel originChannel;

    private AsrServiceGrpc.AsrServiceStub asrServiceStub;

    @PostConstruct
    public void init(){
        this.originChannel = ManagedChannelBuilder.forAddress("localhost", 8051)
                .usePlaintext().build();
        ClientInterceptor interceptor = new HeaderClientInterceptor();
        // 构建Channel时注入客户端拦截器
        Channel channel = ClientInterceptors.intercept(originChannel, interceptor);
        this.asrServiceStub = AsrServiceGrpc.newStub(channel);

        log.info("grpc连接初始化成功");
    }

    public void handle(){
        StreamObserver<AudioStreaming.AudioFragmentResponse> responseObserver =
                new StreamObserver<AudioStreaming.AudioFragmentResponse>() {
            public void onNext(AudioStreaming.AudioFragmentResponse result) {
                log.info("客户端收到请求:'{}'", result.getErrorMessage());
            }

            public void onError(Throwable throwable) {
                log.error("客户端错误", throwable);
            }
            public void onCompleted() {
                log.info("客户端完成处理");
            }
        };

        StreamObserver<AudioStreaming.AudioFragmentRequest> send = asrServiceStub.send(responseObserver);
        List<byte[]> bytes = handelStream();
        bytes.forEach(item->{
            AudioStreaming.AudioFragmentRequest build = AudioStreaming.AudioFragmentRequest
                    .newBuilder()
                    .setSequenceNum(67890)
                    .setAudioData(ByteString.copyFrom(item))
                    .build();
            send.onNext(build);
        });
        send.onCompleted();
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public List<byte[]> handelStream(){
        List<byte[]> buffers = new ArrayList<>();
        File file = new File("/Users/v_zhoujun02/Desktop/16k.wav");
        try (InputStream stream = new FileInputStream(file)) {
            int length = 0;
            while (true){
                byte[] bts = new byte[2560]; // 16k16bit的音频，需要sleep 80ms
                try {
                    length = stream.read(bts);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (length == -1) {
                    break;
                }
                if (length != bts.length) { // 最后一段的length < bts.length
                    byte[] tmp = new byte[length];
                    System.arraycopy(bts, 0, tmp, 0, length);
                    buffers.add(tmp);
                } else {
                    buffers.add(bts);
                }
            }
            if (buffers.size() == 1) {
                byte[] bts = new byte[1];
                buffers.add(bts);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffers;
    }


    @PreDestroy
    public void destory(){
        try {
            this.originChannel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
